// ADCardBase.cpp: implementation of the CADCardBase class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ADCardBase.h"

#pragma comment (lib, ".\\lib\\adsapi32.lib")

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CADCardBase::CADCardBase()
{

}

CADCardBase::CADCardBase(ULONG devicenum) :
m_dwDeviceNum(devicenum),
m_hDriverHandle(0)
{
	//ZeroMemory((void*)&m_DevFeatures)
}

CADCardBase::~CADCardBase()
{

}

BOOL CADCardBase::OpenDASCard()
{
    LRESULT error_code;
    char str_error_msg[256];
    error_code = DRV_DeviceOpen(m_dwDeviceNum,
        (LONG far *)&m_hDriverHandle);
    if (error_code != SUCCESS)
    {
        DRV_GetErrorMessage(error_code,(LPSTR)str_error_msg);
        MessageBox(NULL, (LPCSTR)str_error_msg, "Device Open", MB_OK);
        return FALSE;
     }
    return TRUE;
}

BOOL CADCardBase::GetDeviceFeatures(LPDEVFEATURES lpdevfeatures)
{
    LRESULT error_code;
    char str_error_msg[256];
    PT_DeviceGetFeatures ptDevFeatures;
    ptDevFeatures.buffer = lpdevfeatures;
    ptDevFeatures.size = sizeof(DEVFEATURES);
    if ((error_code = DRV_DeviceGetFeatures(m_hDriverHandle,
        (LPT_DeviceGetFeatures)&ptDevFeatures)) != SUCCESS)
    {
        DRV_GetErrorMessage(error_code,(LPSTR)str_error_msg);
        MessageBox(NULL, (LPCSTR)str_error_msg,"Driver Message",MB_OK);
        DRV_DeviceClose((LONG far *)&m_hDriverHandle);
        return 0;
    }
    return TRUE;
}

BOOL CADCardBase::PrepareTransPara(LPT_FAIIntStart pfaiintstart, LPT_FAITransfer pfaitransfer)
{
	HGLOBAL hBuf, hUserBuf;

	// Step 3: Allocate memory for driver
	if((hBuf=(USHORT far *)GlobalAlloc(GHND,
		sizeof(USHORT) * m_sUserSetting.m_ulConvNum)) == 0)
	{
		MessageBox(NULL, "Not enough memory for buffer ",
			"High Speed", MB_OK);
		DRV_DeviceClose((LONG far *)&m_hDriverHandle);
		return 0;
	}
	
	// Step 4: Allocate memory for Voltage data or Raw data
	if((hUserBuf=(FLOAT far *)GlobalAlloc(GHND,
		sizeof(FLOAT) * m_sUserSetting.m_ulConvNum)) == 0)
	{
		MessageBox(NULL, "Not enough memory for buffer ",
			"High Speed", MB_OK);
		GlobalFree(hBuf);
		DRV_DeviceClose((LONG far *)&m_hDriverHandle);
		return 0;
	}
	
	// Prepare some informations to run
	pfaiintstart->buffer     = (USHORT far *)GlobalLock(hBuf);
    pfaitransfer->DataBuffer = (FLOAT far  *)GlobalLock(hUserBuf);

	pfaiintstart->TrigSrc    = m_sUserSetting.m_wExtTrig;
	pfaiintstart->SampleRate = m_sUserSetting.m_dwPacerRate;
	pfaiintstart->chan   =m_sUserSetting.m_wStartChl;
	pfaiintstart->gain   = m_DevFeatures.glGainList[m_sUserSetting.m_wGainCode].usGainCde;
	pfaiintstart->count  = m_sUserSetting.m_ulConvNum;
	pfaiintstart->cyclic = m_sUserSetting.m_wCyclicMode;
	if (m_sUserSetting.m_wFifoEnable && m_sUserSetting.m_wFifoSize)
		pfaiintstart->IntrCount = m_sUserSetting.m_wFifoSize;
	else
               pfaiintstart->IntrCount = 1;
	return TRUE;
}


BOOL CADCardBase::InitEventFeature()
{
	LRESULT error_code;
    char str_error_msg[256];
	m_ptEnableEvent.EventType = ADS_EVT_INTERRUPT  |
		ADS_EVT_BUFCHANGE  |
		ADS_EVT_TERMINATED |
		ADS_EVT_OVERRUN;
	m_ptEnableEvent.Enabled = m_sUserSetting.m_wEvtFlag;
	m_ptEnableEvent.Count   = m_sUserSetting.m_wFifoEnable ? m_sUserSetting.m_wFifoSize : 1;
	if ((error_code = DRV_EnableEvent(m_hDriverHandle,
		(LPT_EnableEvent)&m_ptEnableEvent)) != 0)
	{
		DRV_GetErrorMessage(error_code, (LPSTR)str_error_msg);
		MessageBox(NULL, (LPCSTR)str_error_msg, "Driver Message", MB_OK);
		GlobalUnlock(m_ptFAIIntStart.buffer);
		GlobalUnlock(m_ptFAITransfer.DataBuffer);
		GlobalFree(m_ptFAIIntStart.buffer);
		GlobalFree(m_ptFAITransfer.DataBuffer);
		DRV_DeviceClose((LONG far *)&m_hDriverHandle);
		return FALSE;
    }
	return TRUE;
}

UINT CADCardBase::ADTransThread(LPVOID pParam)
{
	CADCardBase* pMainThread = (CADCardBase*)pParam;
	USHORT usEventType;
    LONG  ErrCde;
    ULONG gulIntCounter = 0;
    ULONG gulBfChgCounter = 0;
    ULONG gulOverrunCounter = 0;
	//char szCounter[80];

	while(1)
    {
        // Check message
        pMainThread->m_ptCheckEvent.EventType = &usEventType;
        //ptCheckEvent.Milliseconds = 5000;
		
		//
		// Shengkui modified, 2004/02/01
		// if external trigger source enabled, set the 
		// timeout interval to INFINITE
		if ( (pMainThread->m_sUserSetting.m_wExtTrig) || (pMainThread->m_sUserSetting.m_wCyclicMode) )
		{
			pMainThread->m_ptCheckEvent.Milliseconds = INFINITE;
		}
		else
		{
			pMainThread->m_ptCheckEvent.Milliseconds = 1000 * (pMainThread->m_sUserSetting.m_ulConvNum / pMainThread->m_sUserSetting.m_dwPacerRate) + 1000;
		}
		
        if ((ErrCde = DRV_CheckEvent(pMainThread->m_hDriverHandle,
            (LPT_CheckEvent)&pMainThread->m_ptCheckEvent)) != 0)
        {
            MessageBox(NULL, "Check Event Error !", "Thread Message", MB_OK);
			//ReleaseDC(NULL, hdc);
            return 0;
        }
		
        // Process interrupt event
        if (usEventType & ADS_EVT_INTERRUPT)
		{
			gulIntCounter++;
            pMainThread->adInterruptEvent();
		}
		
        // Process buffer change event
        if (usEventType & ADS_EVT_BUFCHANGE)
		{
			gulBfChgCounter++;
            pMainThread->adBufChangeEvent();
		}
		
        // Process overrun event
        if (usEventType & ADS_EVT_OVERRUN)
		{
			gulOverrunCounter++;
            pMainThread->adOverrunEvent();
		}
		
        // Process terminate event
        if (usEventType & ADS_EVT_TERMINATED)
        {
            pMainThread->adTerminateEvent();			
            return 0;
        }
// 		sprintf( szCounter, "Interrupt Counter = %4d\n", gulIntCounter );
// 		TextOut( hdc, 300, 50, szCounter, 24 );  
// 		sprintf( szCounter, "Buffer change Counter = %4d\n", gulBfChgCounter );
// 		TextOut( hdc, 300, 70, szCounter, 28 );
// 		sprintf( szCounter, "Overrun Counter = %4d\n", gulOverrunCounter );
// 		TextOut( hdc, 300, 90, szCounter, 22 );
// 		UpdateWindow( hWnd );
    }

	return 0;
}

void CADCardBase::adInterruptEvent()
{

}

void CADCardBase::adBufChangeEvent()
{
	LONG  ErrCde;
	char        szErrMsg[80]; 

	m_ptFAICheck.ActiveBuf = &m_FAICheckValue.m_wActiveBuf;
    m_ptFAICheck.stopped   = &m_FAICheckValue.m_wStopped;
    m_ptFAICheck.retrieved = &m_FAICheckValue.m_ulRetrieved;
    m_ptFAICheck.overrun   = &m_FAICheckValue.m_wOverrun;
    m_ptFAICheck.HalfReady = &m_FAICheckValue.m_wHalfReady;
	
    if ((ErrCde = DRV_FAICheck(m_hDriverHandle,
		(LPT_FAICheck)&m_ptFAICheck)) != 0)
    {
        DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
        MessageBox(NULL, (LPCSTR)szErrMsg,"Thread Message",MB_OK);
        return ;
    }
	
    if (m_FAICheckValue.m_wHalfReady == 1)  // first ready
    {
        m_ptFAITransfer.ActiveBuf = 0;   // single buffer
        m_ptFAITransfer.DataType = m_sUserSetting.m_wDataType;
        m_ptFAITransfer.start    = 0;
        m_ptFAITransfer.count    = m_sUserSetting.m_ulConvNum/2;
        m_ptFAITransfer.overrun  = &m_FAICheckValue.m_wOverrun;
		
        if ((ErrCde = DRV_FAITransfer(m_hDriverHandle,
            (LPT_FAITransfer)&m_ptFAITransfer)) != 0)
        {
            DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
            MessageBox(NULL,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
            return ;
        }
    }
    else if (m_FAICheckValue.m_wHalfReady == 2) // second half ready
    {
        m_ptFAITransfer.ActiveBuf = 0;   // single buffer
        m_ptFAITransfer.DataType = m_sUserSetting.m_wDataType;
        m_ptFAITransfer.start    = m_sUserSetting.m_ulConvNum/2;
        m_ptFAITransfer.count    = m_sUserSetting.m_ulConvNum/2;
        m_ptFAITransfer.overrun  = &m_FAICheckValue.m_wOverrun;
		
        if ((ErrCde = DRV_FAITransfer(m_hDriverHandle,
            (LPT_FAITransfer)&m_ptFAITransfer)) != 0)
        {
            DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
            MessageBox(NULL, (LPCSTR)szErrMsg,"Thread Message",MB_OK);
            return ;
        }
		
        m_sUserSetting.m_wCyclicCount++;
    }
	
    return;
}

void CADCardBase::adOverrunEvent()
{
	// clear overrun
	LONG  ErrCde;
	char  szErrMsg[80]; 

    if ((ErrCde = DRV_ClearOverrun(m_hDriverHandle)) != 0)
    {
        DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
        MessageBox(NULL, (LPCSTR)szErrMsg, "Thread Message", MB_OK);
        return ;
    }	
    return;
}
	
void CADCardBase::adTerminateEvent()
{
	LONG  ErrCde;
	char  szErrMsg[80];
    // Get real voltage of buffer from driver
    m_ptFAITransfer.ActiveBuf = 0;   // single buffer
    m_ptFAITransfer.DataType = m_sUserSetting.m_wDataType;
    m_ptFAITransfer.start    = 0;
    m_ptFAITransfer.count    = m_sUserSetting.m_ulConvNum;
    m_ptFAITransfer.overrun  = &m_FAICheckValue.m_wOverrun;
	
    if ((ErrCde = DRV_FAITransfer(m_hDriverHandle,
        (LPT_FAITransfer)&m_ptFAITransfer)) != 0)
    {
        DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
        MessageBox(NULL, (LPCSTR)szErrMsg, "Thread Message", MB_OK);
        return ;
    }
	
    // Display data
    //DialogBox (hInstance, MAKEINTRESOURCE(IDD_DATA), hWnd, lpfnShowDataDlgProc) ;
	
    // Free buffer
    GlobalUnlock(m_ptFAIIntStart.buffer);
    GlobalUnlock(m_ptFAITransfer.DataBuffer);
    GlobalFree(m_ptFAIIntStart.buffer);
    GlobalFree(m_ptFAITransfer.DataBuffer);
	
    // Close driver
    DRV_DeviceClose((LONG far *)&m_hDriverHandle);
	
    //EnableMenuItem(hMenu, IDM_RUN, MF_ENABLED | MF_BYCOMMAND);
	
    return;
}

void CADCardBase::StartADTransInt()
{
	if (OpenDASCard())
	{
		PrepareTransPara(&m_ptFAIIntStart, &m_ptFAITransfer);

	}	
}

void CADCardBase::StopADTransInt()
{

}

